package ifest.ontology;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.xml.parsers.ParserConfigurationException;

import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.AddImport;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.MissingImportEvent;
import org.semanticweb.owlapi.model.MissingImportListener;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLImportsDeclaration;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.OWLOntologyStorageException;
import org.semanticweb.owlapi.model.SWRLAtom;
import org.semanticweb.owlapi.model.SWRLObjectPropertyAtom;
import org.semanticweb.owlapi.model.SWRLRule;
import org.semanticweb.owlapi.model.SWRLVariable;
import org.semanticweb.owlapi.reasoner.ConsoleProgressMonitor;
import org.semanticweb.owlapi.reasoner.Node;
import org.semanticweb.owlapi.reasoner.NodeSet;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.reasoner.OWLReasonerConfiguration;
import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;
import org.semanticweb.owlapi.reasoner.SimpleConfiguration;
import org.semanticweb.owlapi.util.DefaultPrefixManager;
import org.semanticweb.owlapi.util.OWLOntologyMerger;
import org.semanticweb.owlapi.util.SimpleIRIMapper;
import org.xml.sax.SAXException;

import com.clarkparsia.modularity.test.AxiomBasedIncrementalClassifierTest;
import com.clarkparsia.pellet.owlapiv3.PelletReasonerFactory;

public class ReasonerTest {
	public String run() throws OWLOntologyCreationException {
		String rs = "";
		// Test for getting ontology list from repository
		/*
		 * System.out.println(OWLIMTool.getOntologyList()); //Test for get
		 * ontology String context = "file://C:/fakepath/ifest-rdf.owl"; for
		 * (String s: OWLIMTool.getOWL(context)) { System.out.println(s); }
		 * //Test for save and load ontology String fileName =
		 * "D://Working/ontologies/test.owl"; // OWLIMTool.getOWL(context,
		 * fileName);
		 */
		OWLOntologyManager manager = OWLManager.createOWLOntologyManager();

		IRI iri = IRI
				.create("http://sqwrl.stanford.edu/ontologies/built-ins/3.4/sqwrl.owl");
		File file = new File("D://Working/ontologies/lib/sqwrl.owl");
		manager.addIRIMapper(new SimpleIRIMapper(iri, IRI.create(file)));
		iri = IRI.create("http://swrl.stanford.edu/ontologies/3.3/swrla.owl");
		file = new File("D://Working/ontologies/lib/swrla.owl");
		manager.addIRIMapper(new SimpleIRIMapper(iri, IRI.create(file)));
		iri = IRI.create("http://www.spem-ifest.org/ontology/metamodel.owl");
		file = new File("D://Working/ontologies/MetaModel.owl");
		manager.addIRIMapper(new SimpleIRIMapper(iri, IRI.create(file)));
		iri = IRI.create("http://www.spem-ifest.org/ontology/metamodel/DI.owl");
		file = new File("D://Working/ontologies/MM_DI.owl");
		manager.addIRIMapper(new SimpleIRIMapper(iri, IRI.create(file)));
		iri = IRI
				.create("http://www.spem-ifest.org/ontology/metamodel/mopcom.owl");
		file = new File("D://Working/ontologies/MM_MOPCOM.owl");
		manager.addIRIMapper(new SimpleIRIMapper(iri, IRI.create(file)));
		file = new File("D://Working/ontologies/mopcom-di-mapping.owl");
		OWLOntology ont = manager.loadOntologyFromOntologyDocument(file);
		System.out.println("load ontology: " + ont.toString());

		OWLDataFactory factory = manager.getOWLDataFactory();
		// We need to create an instance of OWLReasoner. An OWLReasoner provides
		// the basic
		// query functionality that we need, for example the ability obtain the
		// subclasses
		// of a class etc. To do this we use a reasoner factory.

		// Create a reasoner factory. In this case, we will use HermiT, but we
		// could also
		// use FaCT++ (http://code.google.com/p/factplusplus/) or
		// Pellet(http://clarkparsia.com/pellet)
		// Note that (as of 03 Feb 2010) FaCT++ and Pellet OWL API 3.0.0
		// compatible libraries are
		// expected to be available in the near future).

		// For now, we'll use HermiT
		// HermiT can be downloaded from http://hermit-reasoner.com
		// Make sure you get the HermiT library and add it to your class path.
		// You can then
		// instantiate the HermiT reasoner factory:
		// Comment out the first line below and uncomment the second line below
		// to instantiate
		// the HermiT reasoner factory. You'll also need to import the
		// org.semanticweb.HermiT.Reasoner
		// package.
		// OWLReasonerFactory reasonerFactory = null;
		OWLReasonerFactory reasonerFactory = new PelletReasonerFactory();

		// We'll now create an instance of an OWLReasoner (the implementation
		// being provided by HermiT as
		// we're using the HermiT reasoner factory). The are two categories of
		// reasoner, Buffering and
		// NonBuffering. In our case, we'll create the buffering reasoner, which
		// is the default kind of reasoner.
		// We'll also attach a progress monitor to the reasoner. To do this we
		// set up a configuration that
		// knows about a progress monitor.

		// Create a console progress monitor. This will print the reasoner
		// progress out to the console.
		ConsoleProgressMonitor progressMonitor = new ConsoleProgressMonitor();
		// Specify the progress monitor via a configuration. We could also
		// specify other setup parameters in
		// the configuration, and different reasoners may accept their own
		// defined parameters this way.
		OWLReasonerConfiguration config = new SimpleConfiguration(
				progressMonitor);
		// Create a reasoner that will reason over our ontology and its imports
		// closure. Pass in the configuration.
		OWLReasoner reasoner = reasonerFactory.createReasoner(ont, config);

		// Ask the reasoner to do all the necessary work now
		reasoner.precomputeInferences();
		// We can determine if the ontology is actually consistent (in this
		// case, it should be).
		boolean consistent = reasoner.isConsistent();
		System.out.println("Consistent: " + consistent);
		System.out.println("\n");

		// We can easily get a list of unsatisfiable classes. (A class is
		// unsatisfiable if it
		// can't possibly have any instances). Note that the
		// getUnsatisfiableClasses method
		// is really just a convenience method for obtaining the classes that
		// are equivalent
		// to owl:Nothing. In our case there should be just one unsatisfiable
		// class - "mad_cow"
		// We ask the reasoner for the unsatisfiable classes, which returns the
		// bottom node
		// in the class hierarchy (an unsatisfiable class is a subclass of every
		// class).
		Node<OWLClass> bottomNode = reasoner.getUnsatisfiableClasses();
		// This node contains owl:Nothing and all the classes that are
		// equivalent to owl:Nothing -
		// i.e. the unsatisfiable classes.
		// We just want to print out the unsatisfiable classes excluding
		// owl:Nothing, and we can
		// used a convenience method on the node to get these
		Set<OWLClass> unsatisfiable = bottomNode.getEntitiesMinusBottom();
		if (!unsatisfiable.isEmpty()) {
			System.out.println("The following classes are unsatisfiable: ");
			for (OWLClass cls : unsatisfiable) {
				System.out.println("    " + cls);
			}
		} else {
			System.out.println("There are no unsatisfiable classes");
		}
		System.out.println("\n");

		// Get all ToolTypeArtifact
		OWLDataFactory fac = manager.getOWLDataFactory();
		// Test 1
		OWLClass eclass = fac
				.getOWLClass(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#EClass"));
		NodeSet<OWLNamedIndividual> individualsNodeSet = reasoner.getInstances(
				eclass, true);
		Set<OWLNamedIndividual> individuals = individualsNodeSet.getFlattened();
		System.out.println("Instances: ");
		// rs+="Instances of ToolArtifact: ";
		for (OWLNamedIndividual ind : individuals) {
			System.out.println("    " + ind);
			// rs=rs+ "    " + ind.toStringID();
			Node<OWLNamedIndividual> same_indis = reasoner
					.getSameIndividuals(ind);
			System.out.println("same as ");
			// rs+=" same as ";
			Iterator<OWLNamedIndividual> ite = same_indis.iterator();
			OWLNamedIndividual same_indi = null;
			while (ite.hasNext()) {
				same_indi = ite.next();
				if (!same_indi.equals(ind)) {
					rs += same_indi.toStringID();
					System.out.println(same_indi.toStringID());
				}

			}

			System.out.println("---end\n");

		}
		// Test 2
		OWLClass eclass2 = fac
				.getOWLClass(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#EClass"));
		individualsNodeSet = reasoner.getInstances(eclass, true);
		individuals = individualsNodeSet.getFlattened();
		OWLObjectProperty ob_classmap = fac
				.getOWLObjectProperty(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#Class_maps"));
		for (OWLNamedIndividual ind : individuals) {
			System.out.println(ind.toStringID());
			NodeSet<OWLNamedIndividual> list_map = reasoner
					.getObjectPropertyValues(ind, ob_classmap);
			Set<OWLNamedIndividual> list = list_map.getFlattened();
			for (OWLNamedIndividual ind2 : list) {
				System.out.println("correspond with " + ind2.toStringID());
			}
			System.out.println("---end\n");

		}
		// rs+=";\n";
		return rs;
	}

	private static void print(Node<OWLClass> parent, OWLReasoner reasoner,
			int depth) {
		// We don't want to print out the bottom node (containing owl:Nothing
		// and unsatisfiable classes)
		// because this would appear as a leaf node everywhere
		if (parent.isBottomNode()) {
			return;
		}
		// Print an indent to denote parent-child relationships
		printIndent(depth);
		// Now print the node (containing the child classes)
		printNode(parent);
		for (Node<OWLClass> child : reasoner.getSubClasses(
				parent.getRepresentativeElement(), true)) {
			// Recurse to do the children. Note that we don't have to worry
			// about cycles as there
			// are non in the inferred class hierarchy graph - a cycle gets
			// collapsed into a single
			// node since each class in the cycle is equivalent.
			print(child, reasoner, depth + 1);
		}
	}

	private static void printIndent(int depth) {
		for (int i = 0; i < depth; i++) {
			System.out.print("    ");
		}
	}

	private static DefaultPrefixManager pm = new DefaultPrefixManager(
			"http://www.obeonetwork.org/ontologies/spem/ifest.owl#");

	private static void printNode(Node<OWLClass> node) {
		// Print out a node as a list of class names in curly brackets
		System.out.print("{");
		for (Iterator<OWLClass> it = node.getEntities().iterator(); it
				.hasNext();) {
			OWLClass cls = it.next();
			// User a prefix manager to provide a slightly nicer shorter name
			System.out.print(pm.getShortForm(cls));
			if (it.hasNext()) {
				System.out.print(" ");
			}
		}
		System.out.println("}");
	}

	public void generateTransformation() throws OWLOntologyCreationException,
			SAXException, IOException, ParserConfigurationException,
			OWLOntologyStorageException {
		String ifestURI = "http://www.spem-ifest.org";
		String mappingURI = "http://www.spem-ifest.org/ontology/metamodel/mapping.owl";
		String metamodeURI = "http://www.spem-ifest.org/ontology/metamodel.owl";
		String diURI = "http://www.spem-ifest.org/ontology/metamodel/di.owl";
		String mopcomURI = "http://www.spem-ifest.org/ontology/metamodel/mopcom.owl";
		String bluebeeURI = "http://www.spem-ifest.org/ontology/metamodel/bluebee.owl";
		String artifactDefinition1 = "http://www.spem-ifest.org/ontology/instance1.owl#MethodArtifactDefinition_MoPCom_Application_Viewpoint_MetaModel";
		String artifactDefinition2 = "http://www.spem-ifest.org/ontology/instance1.owl#MethodArtifactDefinition_BlueBee_Application_Viewpoint_metamodel";
		String tempFile = "D://Working/temp12345.owl";
		OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
		manager.setSilentMissingImportsHandling(true);
		manager.addMissingImportListener(new MissingImportListener() {

			@Override
			public void importMissing(MissingImportEvent arg0) {
				// TODO Auto-generated method stub
				System.out.println("Warning: load ontology "+arg0.getImportedOntologyURI().toString()+" failed");
				return;
			}
		});
		
		IRI iri = IRI
				.create("http://sqwrl.stanford.edu/ontologies/built-ins/3.4/sqwrl.owl");
		File file = new File("D://Working/ontologies/lib/sqwrl.owl");
		manager.addIRIMapper(new SimpleIRIMapper(iri, IRI.create(file)));
		iri = IRI.create("http://swrl.stanford.edu/ontologies/3.3/swrla.owl");
		file = new File("D://Working/ontologies/lib/swrla.owl");
		manager.addIRIMapper(new SimpleIRIMapper(iri, IRI.create(file)));

		OWLIMTool.getOWL(metamodeURI, tempFile);
		OWLOntology ont = manager.loadOntologyFromOntologyDocument(new File(
				tempFile));
		System.out.println(ont.toString());
		OWLIMTool.getOWL(mopcomURI, tempFile);
		ont = manager.loadOntologyFromOntologyDocument(new File(tempFile));
		System.out.println(ont.toString());
		OWLIMTool.getOWL(bluebeeURI, tempFile);
		ont = manager.loadOntologyFromOntologyDocument(new File(tempFile));
		System.out.println(ont.toString());
		OWLIMTool.getOWL(diURI, tempFile);
		ont = manager.loadOntologyFromOntologyDocument(new File(tempFile));
		System.out.println(ont.toString());
		OWLIMTool.getOWL(mappingURI, tempFile);
		ont = manager.loadOntologyFromOntologyDocument(new File(tempFile));
		System.out.println(ont.toString());
		OWLDataFactory fac = manager.getOWLDataFactory();
		// ////////////////////////////////////
		///////////////////////////////////////
		// /Create rule//////////////////////////
		//////////////////////////////////////////
		//////////////////////////////////////////
		// metamodel-class relation rule///
		//////////////////////////////////
		OWLObjectProperty op_hasClass = fac
				.getOWLObjectProperty(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#MetaModel_classes"));
		OWLObjectProperty op_itsMetaModel = fac
				.getOWLObjectProperty(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#itsMetaModel"));
		SWRLVariable varX = fac.getSWRLVariable(IRI.create(ifestURI + "#x"));
		SWRLVariable varY = fac.getSWRLVariable(IRI.create(ifestURI + "#y"));
		SWRLObjectPropertyAtom propAtom1 = fac.getSWRLObjectPropertyAtom(
				op_hasClass, varX, varY);
		SWRLObjectPropertyAtom propAtom2 = fac.getSWRLObjectPropertyAtom(
				op_itsMetaModel, varY, varX);
		SWRLRule rule1 = fac.getSWRLRule(Collections.singleton(propAtom1),
				Collections.singleton(propAtom2));
		manager.applyChange(new AddAxiom(ont, rule1));
		//end rule 1
		/////////////////////
		//metamodel-reference relation rule
		////////////////////////////////
		OWLObjectProperty op_hasReference = fac
				.getOWLObjectProperty(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#MetaModel_references"));
		 propAtom1 = fac.getSWRLObjectPropertyAtom(
				op_hasReference, varX, varY);
		propAtom2 = fac.getSWRLObjectPropertyAtom(
				op_itsMetaModel, varY, varX);
		SWRLRule rule2 = fac.getSWRLRule(Collections.singleton(propAtom1),
				Collections.singleton(propAtom2));
		manager.applyChange(new AddAxiom(ont, rule2));
		//////////////////////
		// mapping inference rule
		///////////////////////////
		OWLClass eclass = fac
				.getOWLClass(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#EClass"));
		OWLClass reference = fac.getOWLClass(IRI.create(metamodeURI
				+ "#EReference"));
		OWLObjectProperty ob_classmap = fac
				.getOWLObjectProperty(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#Class_maps"));
		OWLIndividual mopcom = fac
				.getOWLNamedIndividual(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel/mopcom.owl#MetaModel_MoPCom"));
		OWLIndividual bluebee = fac
				.getOWLNamedIndividual(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel/bluebee.owl#MetaModel_Bluebee"));
		OWLObjectProperty op_class = fac
				.getOWLObjectProperty(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#MetaModel_classes"));

		SWRLVariable varZ = fac.getSWRLVariable(IRI.create(ifestURI + "#z"));
		propAtom1 = fac.getSWRLObjectPropertyAtom(op_class,
				fac.getSWRLIndividualArgument(mopcom), varX);
		propAtom2 = fac.getSWRLObjectPropertyAtom(op_class,
				fac.getSWRLIndividualArgument(bluebee), varY);
		SWRLObjectPropertyAtom propAtom3 = fac.getSWRLObjectPropertyAtom(
				ob_classmap, varX, varZ);
		SWRLObjectPropertyAtom propAtom4 = fac.getSWRLObjectPropertyAtom(
				ob_classmap, varY, varZ);
		SWRLObjectPropertyAtom propAtom5 = fac.getSWRLObjectPropertyAtom(
				ob_classmap, varX, varY);
		Set<SWRLAtom> antecedent = new HashSet<SWRLAtom>();
		antecedent.add(propAtom1);
		antecedent.add(propAtom2);
		antecedent.add(propAtom3);
		antecedent.add(propAtom4);
		SWRLRule rule3 = fac.getSWRLRule(antecedent,
				Collections.singleton(propAtom5));
		manager.applyChange(new AddAxiom(ont, rule3));
		OWLObjectProperty ob_referencemap = fac
				.getOWLObjectProperty(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#Reference_maps"));
		OWLObjectProperty op_reference = fac
				.getOWLObjectProperty(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#MetaModel_references"));
		propAtom1 = fac.getSWRLObjectPropertyAtom(op_reference,
				fac.getSWRLIndividualArgument(mopcom), varX);
		propAtom2 = fac.getSWRLObjectPropertyAtom(op_reference,
				fac.getSWRLIndividualArgument(bluebee), varY);
		propAtom3 = fac.getSWRLObjectPropertyAtom(
				ob_referencemap, varX, varZ);
		propAtom4 = fac.getSWRLObjectPropertyAtom(
				ob_referencemap, varY, varZ);
		 propAtom5 = fac.getSWRLObjectPropertyAtom(
				 ob_referencemap, varX, varY);
		 SWRLRule rule4 = fac.getSWRLRule(antecedent,
					Collections.singleton(propAtom5));
			manager.applyChange(new AddAxiom(ont, rule4));

		// Get ArtifactDefiniton1
		IFEST_Class_Mapping mapping = new IFEST_Class_Mapping(
				"D:/Working/xml/ifestInfo.xml");

		OWLIMTool.getOWL(ifestURI, tempFile);
		ont = manager.loadOntologyFromOntologyDocument(new File(tempFile));
		OWLIMTool.getOWL("http://www.spem-ifest.org/instance.owl", tempFile);
		// OWLIMTool.getOWL(null, tempFile,artifactDefinition1);
		OWLOntology ont2 = manager.loadOntologyFromOntologyDocument(new File(
				tempFile));
		OWLOntologyMerger merger = new OWLOntologyMerger(manager);
		OWLOntology merged = merger.createMergedOntology(manager,
				IRI.create("http://mergedontology.com"));
		OWLReasonerFactory reasonerFactory = new PelletReasonerFactory();

		// We'll now create an instance of an OWLReasoner (the implementation
		// being provided by HermiT as
		// we're using the HermiT reasoner factory). The are two categories of
		// reasoner, Buffering and
		// NonBuffering. In our case, we'll create the buffering reasoner, which
		// is the default kind of reasoner.
		// We'll also attach a progress monitor to the reasoner. To do this we
		// set up a configuration that
		// knows about a progress monitor.

		// Create a console progress monitor. This will print the reasoner
		// progress out to the console.
		ConsoleProgressMonitor progressMonitor = new ConsoleProgressMonitor();
		// Specify the progress monitor via a configuration. We could also
		// specify other setup parameters in
		// the configuration, and different reasoners may accept their own
		// defined parameters this way.
		OWLReasonerConfiguration config = new SimpleConfiguration(
				progressMonitor);
		// Create a reasoner that will reason over our ontology and its imports
		// closure. Pass in the configuration.
		OWLReasoner reasoner = reasonerFactory.createReasoner(merged, config);

		// Ask the reasoner to do all the necessary work now
		reasoner.precomputeInferences();
		// We can determine if the ontology is actually consistent (in this
		// case, it should be).
		boolean consistent = reasoner.isConsistent();
		System.out.println("Consistent: " + consistent);
		System.out.println("\n");

		// We can easily get a list of unsatisfiable classes. (A class is
		// unsatisfiable if it
		// can't possibly have any instances). Note that the
		// getUnsatisfiableClasses method
		// is really just a convenience method for obtaining the classes that
		// are equivalent
		// to owl:Nothing. In our case there should be just one unsatisfiable
		// class - "mad_cow"
		// We ask the reasoner for the unsatisfiable classes, which returns the
		// bottom node
		// in the class hierarchy (an unsatisfiable class is a subclass of every
		// class).
		Node<OWLClass> bottomNode = reasoner.getUnsatisfiableClasses();
		// This node contains owl:Nothing and all the classes that are
		// equivalent to owl:Nothing -
		// i.e. the unsatisfiable classes.
		// We just want to print out the unsatisfiable classes excluding
		// owl:Nothing, and we can
		// used a convenience method on the node to get these
		Set<OWLClass> unsatisfiable = bottomNode.getEntitiesMinusBottom();
		if (!unsatisfiable.isEmpty()) {
			System.out.println("The following classes are unsatisfiable: ");
			for (OWLClass cls : unsatisfiable) {
				System.out.println("    " + cls);
			}
		} else {
			System.out.println("There are no unsatisfiable classes");
		}
		System.out.println("\n");
		OWLDataFactory owlfactory = manager.getOWLDataFactory();

		OWLIndividual owlinArtdef1 = owlfactory.getOWLNamedIndividual(IRI
				.create(artifactDefinition1));
		printArtifactDefinitionStructure(owlinArtdef1, merged, manager);
		// get artifact definition 2
		OWLIndividual owlinArtdef2 = owlfactory.getOWLNamedIndividual(IRI
				.create(artifactDefinition2));
		printArtifactDefinitionStructure(owlinArtdef2, merged, manager);
		//////////////////////////////
		// //////////////////////////
		// Generate Transformation rule:
		// /////////////////////////
		////////////////////////////////
		System.out.println("Generate the transformation from ");
		printShortIRI(owlinArtdef1);
		System.out.print(" to ");
		printShortIRI(owlinArtdef2);
		////////////////////////////
		// 1. get root element and usedReference
		/////////////////////////
		OWLObjectProperty op_rootelement = owlfactory
				.getOWLObjectProperty(IRI
						.create("http://www.obeonetwork.org/ontologies/spem/ifest.owl#ArtifactDefinition_rootElement"));
		OWLIndividual element = owlinArtdef1
				.getObjectPropertyValues(op_rootelement, merged).iterator().next();
	//	System.out.println(owlinArtdef1 + " have root element: ");

//		System.out.println(element.toStringID().substring(
	//			element.toStringID().indexOf("#") + 1));

		OWLObjectProperty op_usedReference = owlfactory
				.getOWLObjectProperty(IRI
						.create("http://www.obeonetwork.org/ontologies/spem/ifest.owl#ArtifactDefinition_useReference"));
		Set<OWLIndividual> setReference = owlinArtdef1.getObjectPropertyValues(
				op_usedReference, merged);
		/////////////////////
		// 2. get classMapping
		///////////////////
		Set<Mapping> classMapping = new HashSet<Mapping>();
		Set<Mapping> referenceMapping = new HashSet<Mapping>();

		NodeSet<OWLNamedIndividual> individualsNodeSet = reasoner.getObjectPropertyValues((OWLNamedIndividual) mopcom, op_hasClass);
		Set<OWLNamedIndividual> individuals = individualsNodeSet.getFlattened();
		for (OWLNamedIndividual ind : individuals) {
		//	System.out.print("MoPCom:");
	//		printShortIRI(ind);
	//		System.out.println();
			NodeSet<OWLNamedIndividual> list_map = reasoner
					.getObjectPropertyValues(ind, ob_classmap);
			Set<OWLNamedIndividual> list = list_map.getFlattened();
			for (OWLNamedIndividual ind2 : list) {

				if(reasoner.getObjectPropertyValues(ind2, op_itsMetaModel).containsEntity((OWLNamedIndividual) bluebee))
					{
					Mapping m = new Mapping();
					m.setSource(ind);
					m.setTarget(ind2);
					classMapping.add(m);
			//		System.out.println("correspond with BlueBee:");
			//	printShortIRI(ind2);
			//	System.out.println();
					}
			}
		}
/////////////////////
// 3. get referenceMapping
///////////////////
		individualsNodeSet = reasoner.getInstances(reference, true);
		individuals = individualsNodeSet.getFlattened();
		OWLObjectProperty op_referencemapping = fac.getOWLObjectProperty(IRI
				.create(metamodeURI + "#Reference_maps"));
		for (OWLNamedIndividual ind : individuals) {
		//	System.out.print("MoPCom:");
		//	printShortIRI(ind);
		//	System.out.println();
			NodeSet<OWLNamedIndividual> list_map = reasoner
					.getObjectPropertyValues(ind, op_referencemapping);
			Set<OWLNamedIndividual> list = list_map.getFlattened();
			for (OWLNamedIndividual ind2 : list) {
				if(reasoner.getObjectPropertyValues(ind2, op_itsMetaModel).containsEntity((OWLNamedIndividual) bluebee))
					{
					Mapping m = new Mapping();
					
					m.setSource(ind);
				m.setTarget(ind2);
				referenceMapping.add(m);
			//		System.out.println("correspond with BlueBee:");
			//		printShortIRI(ind2);
			//		System.out.println();
			}
		}
		}
		System.out.println("retrieve mapping successfully");
		////////////////////////
		//4. generate transformation
		////////////////////////////
		printTransformation2(manager, merged, element, setReference, classMapping, referenceMapping, 0);
	}

	private void printArtifactDefinitionStructure(
			OWLIndividual artifactDefinition, OWLOntology ont,
			OWLOntologyManager manager) {
		OWLDataFactory owlfactory = manager.getOWLDataFactory();
		OWLObjectProperty op_rootelement = owlfactory
				.getOWLObjectProperty(IRI
						.create("http://www.obeonetwork.org/ontologies/spem/ifest.owl#ArtifactDefinition_rootElement"));
		OWLIndividual element = artifactDefinition
				.getObjectPropertyValues(op_rootelement, ont).iterator().next();
		System.out.println(artifactDefinition + " have root element: ");

		System.out.println(element.toStringID().substring(
				element.toStringID().indexOf("#") + 1));

		OWLObjectProperty op_usedReference = owlfactory
				.getOWLObjectProperty(IRI
						.create("http://www.obeonetwork.org/ontologies/spem/ifest.owl#ArtifactDefinition_useReference"));
		Set<OWLIndividual> setReference = artifactDefinition
				.getObjectPropertyValues(op_usedReference, ont);
		System.out.println(artifactDefinition + " uses references: ");
		for (OWLIndividual i : setReference) {
			System.out.println(i.toStringID().substring(
					i.toStringID().indexOf("#") + 1));
		}
		System.out.println("Compute structure:");
		printStructure(element, ont, manager, 0, setReference);
	}

	private void printStructure(OWLIndividual parentElement, OWLOntology ont,
			OWLOntologyManager manager, int level,
			Set<OWLIndividual> usedReference) {
		if (parentElement == null)
			return;
		List<ArtifactDefinitionStructure> artifactDefinitionStructures = new ArrayList<ArtifactDefinitionStructure>();
		OWLDataFactory factory = manager.getOWLDataFactory();
		OWLObjectProperty op_references = factory
				.getOWLObjectProperty(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#Class_references"));
		Set<OWLIndividual> setReference = parentElement
				.getObjectPropertyValues(op_references, ont);

		//for (int i = 0; i < level; i++)
		//	System.out.print("--");
		System.out.print("<"+printShortIRI(parentElement));
		
		for (OWLIndividual i : setReference) {
			if (usedReference.contains(i) == false)
				continue;
			//System.out.print(" <<"
			//		+ i.toStringID().substring(i.toStringID().indexOf("#") + 1)
			//		+ ">> ");
			OWLObjectProperty op_class = factory
					.getOWLObjectProperty(IRI
							.create("http://www.spem-ifest.org/ontology/metamodel.owl#Reference_class"));
			OWLIndividual ref_class = i.getObjectPropertyValues(op_class, ont)
					.iterator().next();
			OWLDataProperty op_isContaining = factory.getOWLDataProperty(IRI.create("http://www.spem-ifest.org/ontology/metamodel.owl#Reference_isContaining"));
			Set<OWLLiteral> setLit = i.getDataPropertyValues(op_isContaining, ont);
			if(!setLit.isEmpty())
			{
				boolean isContaining = setLit.iterator().next().parseBoolean();
				if (!isContaining)
				{
					System.out.print("\t"+printShortIRI(i));
					
					System.out.print("=\""+printShortIRI(ref_class));
					
					System.out.print("\"");
				}
			}
		
			
		}
		
		System.out.print(">");
		System.out.println();
		for (OWLIndividual i : setReference) {
			if (usedReference.contains(i) == false)
				continue;
			//System.out.print(" <<"
			//		+ i.toStringID().substring(i.toStringID().indexOf("#") + 1)
			//		+ ">> ");
			OWLObjectProperty op_class = factory
					.getOWLObjectProperty(IRI
							.create("http://www.spem-ifest.org/ontology/metamodel.owl#Reference_class"));
			OWLIndividual ref_class = i.getObjectPropertyValues(op_class, ont)
					.iterator().next();
			OWLDataProperty op_isContaining = factory.getOWLDataProperty(IRI.create("http://www.spem-ifest.org/ontology/metamodel.owl#Reference_isContaining"));
			Set<OWLLiteral> setLit = i.getDataPropertyValues(op_isContaining, ont);
			if(!setLit.isEmpty())
			{
				boolean isContaining = setLit.iterator().next().parseBoolean();
				if (isContaining)
				{
					printStructure(ref_class, ont, manager, level + 1, usedReference);
				}
				
			}
			else
			{
				printStructure(ref_class, ont, manager, level + 1, usedReference);
			}
			
		}
		
		System.out.print("</"+printShortIRI(parentElement));
		
		
		System.out.print(">");
		System.out.println();
		return;
	}

	private void printTransformation(OWLOntologyManager man, OWLOntology ont,
			OWLIndividual rootElement, Set<OWLIndividual> usedReference,
			Set<Mapping> classMapping, Set<Mapping> referenceMapping, int level) {
		if (rootElement == null)
			return;
		// find all references of rootElement are contains in usedReference
	
		System.out.print("<");
		printShortIRI(rootElement);
		System.out.print("<<<BlueBee:");
		printShortIRI(findMappingResult(classMapping, rootElement));
		System.out.print(">>>");
		OWLDataFactory owlfactory = man.getOWLDataFactory();
		OWLObjectProperty op_usedReference = owlfactory
				.getOWLObjectProperty(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#Class_references"));
		Set<OWLIndividual> list = rootElement.getObjectPropertyValues(
				op_usedReference, ont);
		Set<OWLIndividual> setReference = new HashSet<OWLIndividual>();
		for (OWLIndividual i : list) {

			if (isContainSameIndividual(usedReference, i)) {
				setReference.add(i);
			}
			break;

		}
		// for each reference
		//not contaning element first
		for (OWLIndividual i : setReference) {
			if (usedReference.contains(i) == false)
				continue;
			OWLDataProperty op_isContaining = owlfactory.getOWLDataProperty(IRI.create("http://www.spem-ifest.org/ontology/metamodel.owl#Reference_isContaining"));
			Set<OWLLiteral> setLit = i.getDataPropertyValues(op_isContaining, ont);
			OWLObjectProperty op_class = owlfactory
					.getOWLObjectProperty(IRI
							.create("http://www.spem-ifest.org/ontology/metamodel.owl#Reference_class"));
			OWLIndividual ref_class = i.getObjectPropertyValues(op_class, ont)
					.iterator().next();
			if(!setLit.isEmpty())
			{
				boolean isContaining = setLit.iterator().next().parseBoolean();
				if (!isContaining)
				{
					System.out.print("\t");
					printShortIRI(i);
					System.out.print("=\"");
					printShortIRI(ref_class);
					System.out.print("\"");
					OWLIndividual mappingref = findMappingResult(referenceMapping, i);
					if (mappingref!=null){
						System.out.print("<<<BlueBee:");
						
						printShortIRI(mappingref);
						System.out.print("=\"");
						printShortIRI(mappingref.getObjectPropertyValues(op_class, ont).iterator().next());
						System.out.print("\"");
						System.out.print(">>>");
					}
					
				}
				
			}
	
		}
		System.out.print(">");
		System.out.println();
		for (OWLIndividual i : setReference) {
			if (usedReference.contains(i) == false)
				continue;
			OWLDataProperty op_isContaining = owlfactory.getOWLDataProperty(IRI.create("http://www.spem-ifest.org/ontology/metamodel.owl#Reference_isContaining"));
			Set<OWLLiteral> setLit = i.getDataPropertyValues(op_isContaining, ont);
			OWLObjectProperty op_class = owlfactory
					.getOWLObjectProperty(IRI
							.create("http://www.spem-ifest.org/ontology/metamodel.owl#Reference_class"));
			OWLIndividual ref_class = i.getObjectPropertyValues(op_class, ont)
					.iterator().next();
			if(!setLit.isEmpty())
			{
				boolean isContaining = setLit.iterator().next().parseBoolean();
				if (isContaining)
				{
					printTransformation(man, ont, ref_class, usedReference,
							classMapping, referenceMapping, level);
				}
				
			}
			else
			{
				printTransformation(man, ont, ref_class, usedReference,
						classMapping, referenceMapping, level);
			}
	
			
		}
	System.out.print("</");
		
		printShortIRI(rootElement);
		System.out.print(">");
		System.out.println();
		return;
	}
	private void printTransformation2(OWLOntologyManager man, OWLOntology ont,
			OWLIndividual rootElement, Set<OWLIndividual> usedReference,
			Set<Mapping> classMapping, Set<Mapping> referenceMapping, int level) {
		if (rootElement == null)
			return;
		// find all references of rootElement are contains in usedReference
		String s1="";
		String s2 = "";
		boolean noCorrespond=false;
		s1="<"+printShortIRI(rootElement);
		
		if(findMappingResult(classMapping, rootElement)==null)
			noCorrespond=true;
		if(!noCorrespond)
			s2 = "<" +printShortIRI(findMappingResult(classMapping, rootElement));		
	
		OWLDataFactory owlfactory = man.getOWLDataFactory();
		OWLObjectProperty op_usedReference = owlfactory
				.getOWLObjectProperty(IRI
						.create("http://www.spem-ifest.org/ontology/metamodel.owl#Class_references"));
		Set<OWLIndividual> list = rootElement.getObjectPropertyValues(
				op_usedReference, ont);
		Set<OWLIndividual> setReference = new HashSet<OWLIndividual>();
		for (OWLIndividual i : list) {

			if (isContainSameIndividual(usedReference, i)) {
				setReference.add(i);
				continue;
			}
			

		}
		// for each reference
		//not contaning element first
		for (OWLIndividual i : setReference) {
			if (usedReference.contains(i) == false)
				continue;
			OWLDataProperty op_isContaining = owlfactory.getOWLDataProperty(IRI.create("http://www.spem-ifest.org/ontology/metamodel.owl#Reference_isContaining"));
			Set<OWLLiteral> setLit = i.getDataPropertyValues(op_isContaining, ont);
			OWLObjectProperty op_class = owlfactory
					.getOWLObjectProperty(IRI
							.create("http://www.spem-ifest.org/ontology/metamodel.owl#Reference_class"));
			OWLIndividual ref_class = i.getObjectPropertyValues(op_class, ont)
					.iterator().next();
			if(!setLit.isEmpty())
			{
				boolean isContaining = setLit.iterator().next().parseBoolean();
				if (!isContaining)
				{
					s1=s1+"\t"+printShortIRI(i)+"=\""+printShortIRI(ref_class)+"\"";
					if(!noCorrespond){
					OWLIndividual mappingref = findMappingResult(referenceMapping, i);
					if (mappingref!=null){
						s2=s2+"\t"+printShortIRI(mappingref)+"=\""+printShortIRI(mappingref.getObjectPropertyValues(op_class, ont).iterator().next())+"\"";
					}
					}
				}
				
			}
	
		}
		s1+=">";
		System.out.print(s1);
		if(!noCorrespond)
		{
			s2+=">";
			System.out.print("------------------------"+s2);
			System.out.println();
		}
		else
		{
			System.out.println();
		}
		for (OWLIndividual i : setReference) {
			if (usedReference.contains(i) == false)
				continue;
			OWLDataProperty op_isContaining = owlfactory.getOWLDataProperty(IRI.create("http://www.spem-ifest.org/ontology/metamodel.owl#Reference_isContaining"));
			Set<OWLLiteral> setLit = i.getDataPropertyValues(op_isContaining, ont);
			OWLObjectProperty op_class = owlfactory
					.getOWLObjectProperty(IRI
							.create("http://www.spem-ifest.org/ontology/metamodel.owl#Reference_class"));
			OWLIndividual ref_class = i.getObjectPropertyValues(op_class, ont)
					.iterator().next();
			if(!setLit.isEmpty())
			{
				boolean isContaining = setLit.iterator().next().parseBoolean();
				if (isContaining)
				{
					printTransformation2(man, ont, ref_class, usedReference,
							classMapping, referenceMapping, level);
				}
				
			}
			else
			{
				printTransformation2(man, ont, ref_class, usedReference,
						classMapping, referenceMapping, level);
			}
	
			
		}
		s1= "</"+printShortIRI(rootElement)+">";
		System.out.print(s1);
		if(!noCorrespond)
		{
			s2="</"+printShortIRI(findMappingResult(classMapping, rootElement))+">";
			System.out.print("------------------------"+s2);
			System.out.println();
		}
		else
		{
			System.out.println();
		}
		return;
	}
	private boolean isContainSameIndividual(Set<OWLIndividual> set,
			OWLIndividual ind) {
		for (OWLIndividual i : set) {
			if (i.toStringID().equals(ind.toStringID())) {
				return true;
			}
		}
		return false;
	}

	private OWLIndividual findMappingResult(Set<Mapping> setMapping,
			OWLIndividual ind) {
		for (Mapping m : setMapping) {
			if (ind.toStringID().equals(m.getSource().toStringID())) {
				return m.getTarget();
			}
			if (ind.toStringID().equals(m.getTarget().toStringID())) {
				return m.getSource();
			}
		}
		return null;
	}
	

	private String printShortIRI(OWLIndividual owlIndividual) {
		if(owlIndividual==null)
		{
	//		System.out.print("null");
			return "null";
		}
		String s = owlIndividual.toStringID().substring(
				owlIndividual.toStringID().indexOf("#") + 1);
	//	System.out.print(s);
		return s;
	}
}

class ArtifactDefinitionStructure {
	private OWLIndividual owlClass;
	private List<OWLIndividual> owlReference;

	public OWLIndividual getOwlClass() {
		return owlClass;
	}

	public void setOwlClass(OWLIndividual owlClass) {
		this.owlClass = owlClass;
	}

	public List<OWLIndividual> getOwlReference() {
		return owlReference;
	}

	public void setOwlReference(List<OWLIndividual> owlReference) {
		this.owlReference = owlReference;
	}
}

class Mapping {
	private OWLIndividual source;
	private OWLIndividual target;

	public OWLIndividual getSource() {
		return source;
	}

	public void setSource(OWLIndividual source) {
		this.source = source;
	}

	public OWLIndividual getTarget() {
		return target;
	}

	public void setTarget(OWLIndividual target) {
		this.target = target;
	}

}
